package com.maimang.platform.crm.service.impl;

import com.maimang.platform.annotation.DataScope;
import com.maimang.platform.common.entity.SysDept;
import com.maimang.platform.common.entity.SysDeptTree;
import com.maimang.platform.common.entity.SysUser;
import com.maimang.platform.common.mapper.SysDeptMapper;
import com.maimang.platform.common.mapper.SysUserDeptMapper;
import com.maimang.platform.common.mapper.SysUserMapper;
import com.maimang.platform.common.utils.MapUtil;
import com.maimang.platform.crm.entity.CrmWorkRecord;
import com.maimang.platform.crm.entity.WorkStatistics;
import com.maimang.platform.crm.entity.WorkTreeNode;
import com.maimang.platform.crm.mapper.CrmWorkRecordMapper;
import com.maimang.platform.crm.service.WorkRecordService;
import com.maimang.platform.crm.util.TreeHelper;
import com.maimang.platform.lang.ConvertUtils;
import com.maimang.platform.lang.StringUtils;
import com.maimang.platform.service.DictService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.*;

/**
 * @author Rocky
 * @version 1.0.0
 * @classname CrmWorkRecordServiceImpl
 * @description <br>工作记录服务层实现类</br>
 * @date 2019-09-23 15:42:23
 * @email jintaozhao@qq.com
 */
@Service
public class WorkRecordServiceImpl implements WorkRecordService {

	public static final Logger log = LoggerFactory.getLogger(WorkRecordServiceImpl.class);

	@Autowired
	private CrmWorkRecordMapper workRecordMapper;

	@Autowired
	private SysDeptMapper deptMapper;

	@Autowired
	private SysUserMapper userMapper;

	@Autowired
	private DictService dictService;

	/**
	 * 查询工作记录信息
	 *
	 * @param workId 工作记录ID
	 * @return 工作记录信息
	 */
	@Override
	public CrmWorkRecord selectWorkRecordById(Integer workId) {
		return workRecordMapper.selectCrmWorkRecordById(workId);
	}

	/**
	 * 根据部门id查询所有下属部门，树形结构
	 *
	 * @param deptId 部门id
	 * @return
	 */
	@Override
	public List<SysDeptTree> selectChildren(Long deptId) {
		List<SysDeptTree> deptTrees = deptMapper.selectChildren(deptId);
		deptTrees = TreeHelper.buildTree(deptTrees, deptId);
		return deptTrees;
	}

	/**
	 * 查询工作记录列表
	 *
	 * @param workRecord 工作记录信息
	 * @return 工作记录集合
	 */
	@Override
	public List<CrmWorkRecord> selectWorkRecordList(CrmWorkRecord workRecord) {
		return workRecordMapper.selectCrmWorkRecordList(workRecord);
	}

	/**
	 * 新增工作记录
	 *
	 * @param workRecord 工作记录信息
	 * @return 结果
	 */
	@Override
	public int insertWorkRecord(CrmWorkRecord workRecord) {
		return workRecordMapper.insertCrmWorkRecord(workRecord);
	}

	/**
	 * 修改工作记录
	 *
	 * @param workRecord 工作记录信息
	 * @return 结果
	 */
	@Override
	public int updateWorkRecord(CrmWorkRecord workRecord) {
		return workRecordMapper.updateCrmWorkRecord(workRecord);
	}

	/**
	 * 删除工作记录对象
	 *
	 * @param ids 需要删除的数据ID
	 * @return 结果
	 */
	@Override
	public int deleteWorkRecordByIds(String ids) {
		return workRecordMapper.deleteCrmWorkRecordByIds(ConvertUtils.toStrArray(ids));
	}

	private WorkTreeNode createNode(Long deptId, Long parentId, String deptName) {
		WorkTreeNode treeNode = new WorkTreeNode();
		treeNode.setDeptId(deptId);
		treeNode.setParentId(parentId);
		treeNode.setDeptName(deptName);
		SysDept dept = deptMapper.selectDeptById(deptId);
		treeNode.setParentDeptName(dept.getParentName());
		return treeNode;
	}

	private HashMap<Long, WorkTreeNode> getTreeNodeMap(Long deptId) {
		// 根据查询的根部门搜索其所有下属部门
		List<SysDeptTree> deptTreeList = deptMapper.selectChildren(deptId);
		SysDept curDept = deptMapper.selectDeptById(deptId);
		HashMap<Long, WorkTreeNode> treeNodeMap = new HashMap<>();

		for (SysDeptTree deptTree : deptTreeList) {
			WorkTreeNode treeNode = createNode(deptTree.getDeptId(), deptTree.getParentId(), deptTree.getDeptName());
			treeNodeMap.put(deptTree.getDeptId(), treeNode);
		}
		if (curDept != null) {
			WorkTreeNode curNode = createNode(curDept.getDeptId(), curDept.getParentId(), curDept.getDeptName());
			treeNodeMap.put(curDept.getDeptId(), curNode);
		}
		return treeNodeMap;
	}

	/**
	 * 将数据库中工作记录进行转换
	 *
	 * @param userId
	 * @param deptId
	 * @param type
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	private List<WorkTreeNode> getWorkList(Long userId, Long deptId, String type, Date startTime, Date endTime) {
		List<WorkStatistics> statistics = workRecordMapper.workStatistics(userId, deptId, type, startTime, endTime);

		Map<String, List<WorkStatistics>> map = new HashMap<>();
		for (WorkStatistics statistic : statistics) {
			map.computeIfAbsent(statistic.getUserName(), k -> new ArrayList<>()).add(statistic);
		}
		List<WorkTreeNode> treeNodeList = new ArrayList<>();
		for (List<WorkStatistics> workList : map.values()) {
			WorkTreeNode workTreeNode = new WorkTreeNode();
			for (int i = 0; i < workList.size(); i++) {
				WorkStatistics workStatistics = workList.get(i);
				workTreeNode.setUserName(workStatistics.getUserName());
				workTreeNode.setUserId(workStatistics.getUserId());
				workTreeNode.setDeptId(workStatistics.getDeptId());
				workTreeNode.setDeptName(workStatistics.getDeptName());
				workTreeNode.setParentId(workStatistics.getParentId());
				workTreeNode.setStartDate(workStatistics.getStartDate());
				workTreeNode.setEndDate(workStatistics.getEndDate());
				workTreeNode.setTime(workStatistics.getTime());
				workTreeNode.setType(workStatistics.getType());

				if (workStatistics.getWorkType() == 0) {
					workTreeNode.setCall(workTreeNode.getCall() + workStatistics.getTotal());
				} else if (workStatistics.getWorkType() == 1) {
					workTreeNode.setVisit(workTreeNode.getVisit() + workStatistics.getTotal());
				} else if (workStatistics.getWorkType() == 2) {
					workTreeNode.setSolution(workTreeNode.getSolution() + workStatistics.getTotal());
				} else if (workStatistics.getWorkType() == 3) {
					workTreeNode.setSign(workTreeNode.getSign() + workStatistics.getTotal());
				}
			}

			treeNodeList.add(workTreeNode);
		}

		return treeNodeList;
	}

	/**
	 * 将数据库中工作记录进行转换
	 *
	 * @param userId
	 * @param deptId
	 * @param type
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	private List<WorkTreeNode> getNodeList(Long userId, Long deptId, String type, Date startTime, Date endTime) {
		List<WorkStatistics> statistics = workRecordMapper.workStatistics(userId, deptId, type, startTime, endTime);

		Map<String, List<WorkStatistics>> map = new HashMap<>();
		for (WorkStatistics statistic : statistics) {
			map.computeIfAbsent(statistic.groupKey(), k -> new ArrayList<>()).add(statistic);
		}
		List<WorkTreeNode> treeNodeList = new ArrayList<>();
		for (List<WorkStatistics> workList : map.values()) {
			WorkTreeNode workTreeNode = new WorkTreeNode();
			for (int i = 0; i < workList.size(); i++) {
				WorkStatistics workStatistics = workList.get(i);
				workTreeNode.setUserName(workStatistics.getUserName());
				workTreeNode.setUserId(workStatistics.getUserId());
				workTreeNode.setDeptId(workStatistics.getDeptId());
				workTreeNode.setDeptName(workStatistics.getDeptName());
				workTreeNode.setParentId(workStatistics.getParentId());
				workTreeNode.setStartDate(workStatistics.getStartDate());
				workTreeNode.setEndDate(workStatistics.getEndDate());
				workTreeNode.setTime(workStatistics.getTime());
				workTreeNode.setType(workStatistics.getType());

				if (workStatistics.getWorkType() == 0) {
					workTreeNode.setCall(workTreeNode.getCall() + workStatistics.getTotal());
				} else if (workStatistics.getWorkType() == 1) {
					workTreeNode.setVisit(workTreeNode.getVisit() + workStatistics.getTotal());
				} else if (workStatistics.getWorkType() == 2) {
					workTreeNode.setSolution(workTreeNode.getSolution() + workStatistics.getTotal());
				} else if (workStatistics.getWorkType() == 3) {
					workTreeNode.setSign(workTreeNode.getSign() + workStatistics.getTotal());
				}
			}

			treeNodeList.add(workTreeNode);
		}

		return treeNodeList;
	}

	private Map<String, List<WorkTreeNode>> getWorkMap(Long userId, Long deptId, String type, Date startTime, Date endTime) {

		List<WorkTreeNode> treeNodeList = this.getNodeList(userId, deptId, type, startTime, endTime);

		Map<String, List<WorkTreeNode>> mapWork = new HashMap<>();
		for (WorkTreeNode workTreeNode : treeNodeList) {
			mapWork.computeIfAbsent(workTreeNode.groupKey(), k -> new ArrayList<>()).add(workTreeNode);
		}
		return mapWork;
	}

	private void getTreeData(HashMap<Long, WorkTreeNode> deptMap, List<WorkTreeNode> treeNodeList, Long rootDeptId) {
		for (WorkTreeNode treeNode : treeNodeList) {
			buildWorkTreeMap(deptMap, treeNode, treeNode, rootDeptId);
		}
	}

	/**
	 * @param userId    用户id
	 * @param deptId    部门id
	 * @param type      统计类型： 日 day 周 week 月 month 季 quarter
	 * @param startTime 开始日期
	 * @param endTime   结束日期
	 * @return
	 */
	@Override
	public WorkTreeNode statistics(Long userId, Long deptId, String type, Date startTime, Date endTime) {
		List<WorkTreeNode> treeNodeList = this.getWorkList(userId, deptId, type, startTime, endTime);
		HashMap<Long, WorkTreeNode> deptMap = this.getTreeNodeMap(deptId);
		getTreeData(deptMap, treeNodeList, deptId);
		WorkTreeNode rootNode = deptMap.get(deptId);
		return rootNode;
	}

	/**
	 * 个人工作内容统计
	 *
	 * @param userId
	 * @param deptId
	 * @param type
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	@Override
	public WorkTreeNode personStatistics(Long userId, Long deptId, String type, Date startTime, Date endTime) {
		List<WorkTreeNode> treeNodeList = this.getNodeList(userId, deptId, type, startTime, endTime);
		WorkTreeNode rootNode = new WorkTreeNode();

		for (int i = 0; i < treeNodeList.size(); i++) {
			WorkTreeNode treeNode = treeNodeList.get(i);
			rootNode.setDeptName(treeNode.getDeptName());
			rootNode.setDeptId(treeNode.getDeptId());
			rootNode.setUserName(treeNode.getUserName());
			rootNode.setUserId(treeNode.getUserId());
			rootNode.setParentId(treeNode.getParentId());
			rootNode.setSign(rootNode.getSign() + treeNode.getSign());
			rootNode.setCall(rootNode.getCall() + treeNode.getCall());
			rootNode.setVisit(rootNode.getVisit() + treeNode.getVisit());
			rootNode.setVisit2(rootNode.getVisit2() + treeNode.getVisit2());
			rootNode.setVisit3(rootNode.getVisit2() + treeNode.getVisit3());
			rootNode.setVisit4(rootNode.getVisit4() + treeNode.getVisit4());
			rootNode.setSolution(rootNode.getSolution() + treeNode.getSolution());
		}

		return rootNode;
	}

	/**
	 * 工作内容统计
	 *
	 * @param userId    用户id
	 * @param type      统计类型： 日 day 周 week 月 month 季 quarter
	 * @param startTime 开始日期
	 * @param endTime   结束日期
	 * @return
	 */
	@Override
	public List<WorkTreeNode> workStatistics(Long userId, Long deptId, String type, Date startTime, Date endTime) {
		HashMap<Long, WorkTreeNode> treeNodeMap = this.getTreeNodeMap(deptId);
		if (StringUtils.isEmpty(type))
			type = "month";
		Map<String, List<WorkTreeNode>> mapWork = this.getWorkMap(userId, deptId, type, startTime, endTime);

		List<WorkTreeNode> list = new ArrayList<>();
		for (List<WorkTreeNode> workTreeNodeList : mapWork.values()) {
			HashMap<Long, WorkTreeNode> deptMap = new HashMap<>();
			// deptMap = treeNodeMap;
			MapUtil.mapCopy(treeNodeMap, deptMap);
			for (int i = 0; i < workTreeNodeList.size(); i++) {
				WorkTreeNode treeNode = workTreeNodeList.get(i);
				treeNode = formatWorkTree(deptMap, treeNode, treeNode, deptId);

				if (list.contains(treeNode)) {
					list.remove(treeNode);
				}
				list.add(treeNode);
			}
		}
		return list;
	}

	/**
	 * 工作内容统计
	 *
	 * @param userId    用户id
	 * @param deptId    部门id
	 * @param type      统计类型： 日 day 周 week 月 month 季 quarter
	 * @param startTime 开始日期
	 * @param endTime   结束日期
	 * @return
	 */
	@Override
	public Map<String, WorkTreeNode> worklistForChart(Long userId, Long deptId, String type, Date startTime, Date endTime) {
		List<WorkStatistics> statistics = workRecordMapper.workStatistics(userId, deptId, type, startTime, endTime);
		Map<String, List<WorkTreeNode>> mapWork = this.getWorkMap(userId, deptId, type, startTime, endTime);

		Map<String, WorkTreeNode> resultMap = new HashMap<>();

		for (Map.Entry<String, List<WorkTreeNode>> entry : mapWork.entrySet()) {
			WorkTreeNode node = new WorkTreeNode();
			List<WorkTreeNode> workTreeNodeList = entry.getValue();
			for (int i = 0; i < workTreeNodeList.size(); i++) {
				WorkTreeNode treeNode = workTreeNodeList.get(i);
				node.setTime(treeNode.getTime());
				node.setType(treeNode.getType());
				node.setStartDate(treeNode.getStartDate());
				node.setEndDate(treeNode.getEndDate());
				node.setCall(node.getCall() + treeNode.getCall());
				node.setVisit(node.getVisit() + treeNode.getVisit());
				node.setVisit2(node.getVisit2() + treeNode.getVisit2());
				node.setVisit3(node.getVisit3() + treeNode.getVisit3());
				node.setVisit4(node.getVisit4() + treeNode.getVisit4());
				node.setSolution(node.getSolution() + treeNode.getSolution());
				node.setSign(node.getSign() + treeNode.getSign());
			}
			resultMap.put(entry.getKey(), node);
		}

		return resultMap;
	}

	private HashMap<Long, WorkTreeNode> buildWorkTreeMap(HashMap<Long, WorkTreeNode> deptMap, WorkTreeNode treeNode, WorkTreeNode leafNode, Long rootDeptId) {
		if (treeNode.getDeptId().equals(rootDeptId) && treeNode.getUserId() == null)
			return deptMap;
		WorkTreeNode parentNode = null;
		if (StringUtils.isEmpty(treeNode.getUserName()) || StringUtils.isNull(treeNode.getUserId()))
			parentNode = deptMap.get(treeNode.getParentId());
		else
			parentNode = deptMap.get(treeNode.getDeptId());

		if (StringUtils.isNull(parentNode))
			return deptMap;
		parentNode.setTime(treeNode.getTime());
		parentNode.setType(treeNode.getType());
		parentNode.setStartDate(treeNode.getStartDate());
		parentNode.setEndDate(treeNode.getEndDate());

		List<WorkTreeNode> children = parentNode.getChildren();
		if (children == null)
			children = new ArrayList<>();
		if (children.contains(treeNode)) {
			children.remove(treeNode);
		}

		parentNode.setCall(parentNode.getCall() + leafNode.getCall());
		parentNode.setVisit(parentNode.getVisit() + leafNode.getVisit());
		parentNode.setVisit2(parentNode.getVisit2() + leafNode.getVisit2());
		parentNode.setVisit3(parentNode.getVisit3() + leafNode.getVisit3());
		parentNode.setVisit4(parentNode.getVisit4() + leafNode.getVisit4());
		parentNode.setSolution(parentNode.getSolution() + leafNode.getSolution());
		parentNode.setSign(parentNode.getSign() + leafNode.getSign());
		children.add(treeNode);
		parentNode.setChildren(children);

		return buildWorkTreeMap(deptMap, parentNode, leafNode, rootDeptId);
	}


	/**
	 * 构建小程序图表所需的数据结构
	 *
	 * @param dataMap 工作内容统计
	 * @return
	 */
	@Override
	public Map getChartData(Map<String, WorkTreeNode> dataMap, String type, Date startTime, Date endTime) {
		Map<String, List> chartData = new HashMap<>();

		List categories = new ArrayList<>();
		List series = new ArrayList<>();
		String call = "电话";
		String visit = "拜访";
		String solution = "提案";
		String sign = "签约";

		String callColor = dictService.getValue("crm_chart_color", call);
		String visitColor = dictService.getValue("crm_chart_color", visit);
		String solutionColor = dictService.getValue("crm_chart_color", solution);
		String signColor = dictService.getValue("crm_chart_color", sign);
		List callData = new ArrayList();
		List visitData = new ArrayList();
		List solutionData = new ArrayList();
		List signData = new ArrayList();

		List<WorkTreeNode> list = new ArrayList<>(dataMap.values());
		list.sort((x, y) -> Double.compare(x.getStartDate().getTime(), y.getStartDate().getTime()));

		for (WorkTreeNode node : list) {
			categories.add(node.getTime());
			callData.add(node.getCall());
			visitData.add(node.getVisit());
			solutionData.add(node.getSolution());
			signData.add(node.getSign());
		}

		Map callMap = new HashMap();
		callMap.put("type", call);
		callMap.put("color", callColor);
		callMap.put("data", callData);
		series.add(callMap);

		Map visitMap = new HashMap();
		visitMap.put("type", visit);
		visitMap.put("color", visitColor);
		visitMap.put("data", visitData);
		series.add(visitMap);

		Map solutionMap = new HashMap();
		solutionMap.put("type", solution);
		solutionMap.put("color", solutionColor);
		solutionMap.put("data", solutionData);
		series.add(solutionMap);

		Map signMap = new HashMap();
		signMap.put("type", sign);
		signMap.put("color", signColor);
		signMap.put("data", signData);
		series.add(signMap);

		chartData.put("categories", categories);
		chartData.put("series", series);
		return chartData;
	}

	/**
	 * 数据格式封装
	 *
	 * @param deptMap    部门
	 * @param treeNode   节点数据
	 * @param rootDeptId 根部门id
	 * @return
	 */
	private WorkTreeNode formatWorkTree(HashMap<Long, WorkTreeNode> deptMap, WorkTreeNode treeNode, WorkTreeNode leafNode, Long rootDeptId) {
		if (treeNode.getDeptId().equals(rootDeptId) && treeNode.getUserId() == null)
			return treeNode;
		WorkTreeNode parentNode = null;
		if (StringUtils.isEmpty(treeNode.getUserName()) || StringUtils.isNull(treeNode.getUserId()))
			parentNode = deptMap.get(treeNode.getParentId());
		else
			parentNode = deptMap.get(treeNode.getDeptId());

		SysDept dept = deptMapper.selectDeptById(treeNode.getDeptId());
		if (StringUtils.isNotNull(dept)) {
			treeNode.setDeptName(dept.getDeptName());
			treeNode.setParentDeptName(dept.getParentName());
		}
		SysUser user = userMapper.selectUserById(treeNode.getUserId());
		if (StringUtils.isNotNull(user)) {
			treeNode.setJobNumber(user.getJobNumber());
		}
		if (StringUtils.isNull(parentNode))
			return treeNode;
		parentNode.setTime(treeNode.getTime());
		parentNode.setType(treeNode.getType());
		parentNode.setStartDate(treeNode.getStartDate());
		parentNode.setEndDate(treeNode.getEndDate());

		List<WorkTreeNode> children = parentNode.getChildren();
		if (children == null)
			children = new ArrayList<>();
		if (children.contains(treeNode)) {
			children.remove(treeNode);
		} else {
		}
		parentNode.setCall(parentNode.getCall() + leafNode.getCall());
		parentNode.setVisit(parentNode.getVisit() + leafNode.getVisit());
		parentNode.setVisit2(parentNode.getVisit2() + leafNode.getVisit2());
		parentNode.setVisit3(parentNode.getVisit3() + leafNode.getVisit3());
		parentNode.setVisit4(parentNode.getVisit4() + leafNode.getVisit4());
		parentNode.setSolution(parentNode.getSolution() + leafNode.getSolution());
		parentNode.setSign(parentNode.getSign() + leafNode.getSign());
		children.add(treeNode);
		parentNode.setChildren(children);
		HashMap map = this.getTreeNodeMap(rootDeptId);
		MapUtil.mapCopy(map, deptMap);
		return formatWorkTree(deptMap, parentNode, leafNode, rootDeptId);
	}

	/**
	 * 通过深拷贝获取对象
	 *
	 * @param treeNode 原始对象
	 * @return
	 */
	private WorkTreeNode getWorkTreeNode(WorkTreeNode treeNode) {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		ObjectOutputStream oos = null;
		try {
			oos = new ObjectOutputStream(bos);
			oos.writeObject(treeNode);
			oos.flush();
			ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
			WorkTreeNode target = (WorkTreeNode) ois.readObject();
			return target;
		} catch (Exception e) {
			log.error("获取对象出错", e);
		}
		return null;
	}
}
